home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / ldb.zip / SBINDER.HPP < prev    next >
C/C++ Source or Header  |  1991-10-18  |  8KB  |  339 lines

  1. /*
  2.  
  3.     sbinder.hpp
  4.     10-18-91
  5.     Streamable Binder: Loose Data Binder v 1.4
  6.  
  7.     Copyright 1991
  8.     John W. Small
  9.     All rights reserved
  10.  
  11.     PSW / Power SoftWare
  12.     P.O. Box 10072
  13.     McLean, Virginia 22102 8072 USA
  14.  
  15.     John Small
  16.     Voice: (703) 759-3838
  17.     CIS: 73757,2233
  18.  
  19. */
  20.  
  21.  
  22. #ifndef SBINDER_HPP
  23. #define SBINDER_HPP
  24.  
  25. #include <iostream.h>
  26. #include <iomanip.h>
  27.  
  28. #ifndef BINDER_HPP
  29. #include "binder.hpp"
  30. #endif
  31.  
  32. #define ID_Streamable        0
  33. #define ID_StreamableRef    ID_Streamable
  34. #define ID_SBinder        1
  35.  
  36.  
  37. class Streamable;
  38. typedef Streamable * StreamablE;
  39. #define StreamablE0 ((StreamablE)0)
  40.  
  41. class StreamableClassRegistry;
  42. #define SCRegistry  SCReg
  43. extern StreamableClassRegistry SCRegistry;
  44.  
  45. /*
  46.  
  47.     A class must include the STREAMABLE macro or its
  48.     equivalent in its public section and be derived 
  49.     either publicly or privately from Streamable but 
  50.     never virtually or otherwise multiply inherited 
  51.     in order for it to be "streamable".  Furthermore 
  52.     it must have been linked to.  The SBinder 
  53.     primitives automatically link to and unlink from 
  54.     Streamable nodes.  That means the SBinder must
  55.     itself be linked before it can be streamed.  See
  56.     SBinder below for an example without using the 
  57.     STREAMABLE macro and SData for an example using
  58.     STREAMABLE.
  59.  
  60. */
  61.  
  62. class Streamable  {
  63.     friend StreamableClassRegistry;
  64.     voiD parenT;
  65.     unsigned id;
  66.     unsigned refCount, streamCount;
  67.     long streamPos;
  68. /*
  69.     Stream contents:
  70.  
  71.             1st & Only    1st of Many    MultiRef
  72.  
  73.     id        x               x        0
  74.     refCount    1        > 1
  75.     streamCount
  76.     streamPos                    x
  77.     user's data    x        x
  78. */
  79. protected:
  80.     // Static so that the static load() can call!
  81.     static void lserror(const char *msg, unsigned id);
  82.     virtual void serror(const char *msg);
  83.     virtual void swarn(const char *msg);
  84.     virtual ostream& store(ostream& os)
  85.         { return os; }
  86.     static StreamablE load(istream& is,
  87.         StreamablE InstancE);
  88.     void setID(unsigned id)
  89.         { this->id = id; }
  90. public:
  91.     static int refDebug;
  92.     static int streamDebug;
  93.     static char memberTermChar;
  94.     enum { ID_CLASS = 0 };
  95.     // The first parameter below, "dummy", insures that
  96.     // the STREAMABLE macro defines a unique constructor
  97.     // for derived classes!
  98.     Streamable(StreamableClassRegistry& dummy,
  99.         unsigned id = Streamable::ID_CLASS);
  100.     static void registerClass(unsigned id = ID_CLASS,
  101.         StreamablE (*loader)(istream& is,
  102.         StreamablE InstancE) = load);
  103.     operator StreamablE() { return this; }
  104.     voiD ParenT()  { return parenT; }
  105.     unsigned ID()  { return id; }
  106.     virtual unsigned restream();
  107.     unsigned unlink(voiD P = voiD0);
  108.     StreamablE link(voiD P = voiD0);
  109.     unsigned RefCount()  { return refCount; }
  110.     virtual ~Streamable() {}
  111. };
  112.  
  113.  
  114. // stream manipulator: insert end of member field char
  115.  
  116. extern ostream& endm(ostream& os);
  117.  
  118. // stream manipulator: extract end of member field char
  119.  
  120. extern istream& nextm(istream& is);
  121.  
  122.  
  123. /*
  124.     The STREAMABLE macro declares two functions: store()
  125.     and load() which you must define to store member
  126.     data onto a stream and to load that data back from
  127.     that stream.  You must assign a unique id to each
  128.     streamable class and register every class that will
  129.     be stored on a stream.  Don't forget to restream()
  130.     between operations!
  131. */
  132.  
  133. #define STREAMABLE(class, id, base) \
  134. private:  \
  135.     friend StreamableClassRegistry;  \
  136. protected:  \
  137.     base :: lserror;  \
  138.     base :: serror;  \
  139.     base :: swarn;  \
  140.     virtual ostream& store(ostream& os);  \
  141.     static StreamablE load(istream& is,  \
  142.         StreamablE InstancE);  \
  143.     base :: setID;  \
  144. public:  \
  145.     enum { ID_CLASS = id };  \
  146.     class (StreamableClassRegistry& dummy,  \
  147.         unsigned cid = class ::ID_CLASS) \
  148.         : base (dummy,cid) {}  \
  149.     operator StreamablE()  \
  150.         { return (StreamablE)this; }  \
  151.     static void registerClass(unsigned cid =   \
  152.         class ::ID_CLASS,  \
  153.         StreamablE (*loader)(istream& is,  \
  154.         StreamablE InstancE) = class ::load)  \
  155.         { base :: registerClass(cid,loader); }  \
  156.     base :: ParenT;  \
  157.     base :: ID;  \
  158.     base :: restream;  \
  159.     base :: unlink;  \
  160.     base :: link;  \
  161.     base :: RefCount
  162.     
  163.  
  164. //  value for dummy parameter of constructor above
  165.  
  166. #define UNIQUE_STREAMABLE  SCRegistry
  167.  
  168.  
  169. class SBinder : public Binder, public Streamable  {
  170. protected:
  171.     virtual int  Dfree(voiD D);
  172.     virtual int  Dattach(voiD D);
  173.     virtual void Ddetach(voiD D);
  174.     virtual ostream& store(ostream& os);
  175.     static  StreamablE load(istream& is,
  176.         StreamablE InstancE);
  177.     virtual void Dstore(ostream& os, const voiD D);
  178.     virtual voiD Dload(istream& is);
  179. public:
  180.     enum { ID_CLASS = ID_SBinder };
  181.     SBinder(StreamableClassRegistry& dummy,
  182.         unsigned id = ID_CLASS)
  183.         : Binder(OnlyInitBinderVFT),
  184.         Streamable(dummy,id) {}
  185.     SBinder(unsigned flags = BDR_OK_FREE,
  186.         unsigned maxNodes = BDR_MAXNODES,
  187.         unsigned limit = BDR_LIMIT,
  188.         unsigned delta = BDR_DELTA)
  189.         : Binder(flags,maxNodes,limit,delta),
  190.         Streamable(UNIQUE_STREAMABLE,ID_CLASS)
  191.         {}
  192.     SBinder(voiDV argv, int argc = 0,
  193.         unsigned flags = BDR_OK_FREE)
  194.         : Binder(argv,argc,flags),
  195.         Streamable(UNIQUE_STREAMABLE,ID_CLASS)
  196.         {}
  197.     static void registerClass(unsigned id = ID_CLASS,
  198.         StreamablE (*loader)(istream& is,
  199.         StreamablE InstancE) = load)
  200.         { Streamable :: registerClass(id,loader); }
  201.     virtual unsigned restream();
  202.     virtual ~SBinder();
  203. };
  204.  
  205. typedef SBinder * SBindeR;
  206. #define SBindeR0 ((SBindeR)0)
  207.  
  208.  
  209.  
  210. /*
  211.  
  212.     The StreamableClassRegistry holds the records of
  213.     classes and their static load functions.  Load
  214.     functions have to be static because constructors
  215.     don't have addresses in C++.  Store functions are
  216.     virtual and thus can be called automatically.
  217.  
  218. */
  219.  
  220.  
  221. struct StreamableClassRecord {
  222.     unsigned id;
  223.     StreamablE (*load)(istream& is,
  224.         StreamablE InstancE);
  225.     StreamableClassRecord(unsigned id,
  226.         StreamablE (*load)(istream& is,
  227.             StreamablE InstancE))
  228.         { this->id = id; this->load = load; }
  229. };
  230. typedef StreamableClassRecord * SCRecorD;
  231. #define SCRecorD0 ((SCRecorD)0)
  232.  
  233. struct InstanceHoldingRecord  {
  234.     StreamablE InstancE;
  235.     unsigned refCount, streamCount;
  236.     long streamPos;
  237.     InstanceHoldingRecord(StreamablE InstancE,
  238.         unsigned refCount, long streamPos)
  239.     {
  240.         this->InstancE = InstancE;
  241.         this->refCount = refCount;
  242.         streamCount = 1;
  243.         this->streamPos = streamPos;
  244.     }
  245. };
  246. typedef InstanceHoldingRecord * IHRecorD;
  247. #define IHRecorD0 ((IHRecorD)0)
  248.  
  249.  
  250. class StreamableClassRegistry  {
  251.     Binder ClassRecords;
  252.     Binder InstanceLinks;
  253. protected:
  254.     virtual void error(char *msg, unsigned id = 0,
  255.             StreamablE InstancE = StreamablE0);
  256.     virtual void warn(char *msg, unsigned id = 0,
  257.             StreamablE InstancE = StreamablE0);
  258. public:
  259.     static int debug;
  260.     StreamableClassRegistry()
  261.         : ClassRecords(BDR_OK_FREE),
  262.         InstanceLinks(BDR_OK_FREE)
  263.         {}
  264.     unsigned restream();
  265.     void registerClass(unsigned id, StreamablE (*loader)
  266.         (istream& is, StreamablE InstancE));
  267.     void forgetClasses();
  268.     istream& get(istream& is, StreamablE& InstancE);
  269.     ostream& put(ostream& os, StreamablE InstancE);
  270.     ~StreamableClassRegistry() { forgetClasses(); }
  271. };
  272.  
  273. #define RestreamRegistry()  SCRegistry.restream()
  274.  
  275.  
  276. inline istream& operator>>(istream& is, StreamablE& InstancE)
  277. {
  278.     return SCRegistry.get(is,InstancE);
  279. }
  280.  
  281. inline ostream& operator<<(ostream& os, StreamablE InstancE)
  282. {
  283.     return SCRegistry.put(os, InstancE);
  284. }
  285.  
  286.  
  287.  
  288. /*
  289.  
  290.     FncPtrRegistry is provided so that you can stream
  291.     function pointers.
  292.  
  293. */
  294.  
  295. typedef void (*GenericFnC)();
  296. #define GenericFnC0 ((GenericFnC)0)
  297. #define ID_UnknownGenericFnC    0
  298.  
  299. struct StreamableFncPtrRecord {
  300.     unsigned id;
  301.     GenericFnC fnC;
  302.     StreamableFncPtrRecord(unsigned id,
  303.         GenericFnC fnC)
  304.         { this->id = id; this->fnC = fnC; }
  305. };
  306. typedef StreamableFncPtrRecord * SFPRecorD;
  307. #define SFPRecorD0 ((SFPRecorD)0)
  308.  
  309. class StreamableFncPtrRegistry  {
  310.     Binder FncPtrRecords;
  311. public:
  312.     static int debug;
  313. protected:
  314.     virtual void error(char *msg, unsigned id);
  315.     virtual void warn(char *msg, unsigned id);
  316. public:
  317.     StreamableFncPtrRegistry() : FncPtrRecords()  {}
  318.     void registerFunction(unsigned id,
  319.         GenericFnC fnC);
  320.     GenericFnC FnC(unsigned id);
  321.     unsigned ID(GenericFnC fnC);
  322.     ~StreamableFncPtrRegistry()
  323.         { FncPtrRecords.allFree(); }
  324. };
  325.